/* s^2 - HTTP methods
   Copyright (C) 2018-2019 Ariadne Devos

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

/* Adapted from <sHT/web/method.h> */

#ifndef _sHT_WEB_HEADER_H
#define _sHT_WEB_HEADER_H

#include <stddef.h>
#include <stdint.h>

enum s2_http_header
{
	/* unknown header */
	S2_HTTP_HEADER_UNKNOWN = 0,

	/* (RFC 2616 (HTTP/1.1), 4.5 General Header Fields, p. 34-35)
	  Applicable to both requests and responses.
	  ‘Unrecognized header fields are treated as entity-header fields’ */
	S2_HTTP_GENERAL_CACHE_CONTROL,
	S2_HTTP_GENERAL_CONNECTION,
	S2_HTTP_GENERAL_DATE,
	S2_HTTP_GENERAL_PRAGMA,
	S2_HTTP_GENERAL_TRAILER,
	S2_HTTP_GENERAL_TRANSFER_ENCODING,
	S2_HTTP_GENERAL_UPGRADE,
	S2_HTTP_GENERAL_VIA,
	S2_HTTP_GENERAL_WARNING,

	/* (RFC 2616 (HTTP/1.1), 5.3 Request Header Fields, p. 38-39)
	  Only for requests.
	  ‘Unrecognized header fields are treated as entity-header fields’ */
	S2_HTTP_REQUEST_ACCEPT,
	S2_HTTP_REQUEST_ACCEPT_CHARSET,
	S2_HTTP_REQUEST_ACCEPT_ENCODING,
	S2_HTTP_REQUEST_ACCEPT_LANGUAGE,
	S2_HTTP_REQUEST_AUTHORIZATION,
	S2_HTTP_REQUEST_EXPECT,
	S2_HTTP_REQUEST_FROM,
	S2_HTTP_REQUEST_HOST,
	S2_HTTP_REQUEST_IF_MATCH,
	S2_HTTP_REQUEST_IF_MODIFIED_SINCE,
	S2_HTTP_REQUEST_IF_NONE_MATCH,
	S2_HTTP_REQUEST_IF_RANGE,
	S2_HTTP_REQUEST_IF_UNMODIFIED_SINCE,
	S2_HTTP_REQUEST_MAX_FORWARDS,
	S2_HTTP_REQUEST_PROXY_AUTHORIZATION,
	S2_HTTP_REQUEST_RANGE,
	S2_HTTP_REQUEST_REFERER,
	S2_HTTP_REQUEST_TE,
	S2_HTTP_REQUEST_USER_AGENT,

	/* (RFC 2616 (HTTP/1.1), 6.2 Response Header Fields, p. 41-42)
	  Only for responses.
	  ‘Unrecognized header fields are treated as entity-header fields’ */
	S2_HTTP_RESPONSE_ACCEPT_RANGES,
	S2_HTTP_RESPONSE_AGE,
	S2_HTTP_RESPONSE_ETAG,
	S2_HTTP_RESPONSE_LOCATION,
	S2_HTTP_RESPONSE_PROXY_AUTHENTICATE,
	S2_HTTP_RESPONSE_RETRY_AFTER,
	S2_HTTP_RESPONSE_SERVER,
	S2_HTTP_RESPONSE_VARY,
	S2_HTTP_RESPONSE_WWW_AUTHENTICATE,

	/* (RFC 2616 (HTTP/1.1), 7.1 Entity Header Fields, p. 42)
	  For requests with a body (e.g. POST) or responses.
	  ‘Unrecognized header fields SHOULD be ignored by the recipient’
	  ‘Unrecognized header fields MUST be forwarded by transparent
	  proxies’ */
	S2_HTTP_ENTITY_ALLOW,
	S2_HTTP_ENTITY_CONTENT_ENCODING,
	S2_HTTP_ENTITY_CONTENT_LANGUAGE,
	S2_HTTP_ENTITY_CONTENT_LENGTH,
	S2_HTTP_ENTITY_CONTENT_LOCATION,
	S2_HTTP_ENTITY_CONTENT_MD5,
	S2_HTTP_ENTITY_CONTENT_RANGE,
	S2_HTTP_ENTITY_CONTENT_TYPE,
	S2_HTTP_ENTITY_EXPIRES,
	S2_HTTP_ENTITY_LAST_MODIFIED,
};

#define S2_HTTP_HEADER_MAX S2_HTTP_ENTITY_LAST_MODIFIED

#define S2_HTTP_HEADER_MAX_LENGTH 18

/** Map a header name to its @var{s2_http_header} identifier

  @var{string}: the header name
  @var{length}: the length of the header name -- not its buffer's!

  All first @var{S2_HTTP_HEADER_MAX_LENGTH} characters of @var{string}
  may be read.

  The lookup is case-sensitive; @var{string} must be lowercase for a match,
  in deviance from (RFC 2616 (HTTP/1.1), 4.2 Message Headers, p. 31):
  ‘Field names are case-insensitive’.

  HTTP/2 however requires lowercase
  (RFC 7540 (HTTP/2), 8.1.2 HTTP Header Fields, p. 35)
  ‘Just as in HTTP/1.x, header field names are strings of ASCII characters
  that are compared in a case-insensitive fashion. However, header field
  names MUST be converted to lowercase prior to their encoding in HTTP/2.’

  (One could argue that HTTP/2 header names do not have a concept of
  case and there is a only one canonical encoding -- i.e., lowercase.)

  If no such header is known, return @var{S2_HTTP_HEADER_UNKNOWN}.
  The return value may speculatively be incorrect, but it is always a
  @var{s2_http_header}. */
size_t
s2_http_header_lookup(const uint8_t string[], size_t length);

#endif
